{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from torchtext import data,datasets\n",
    "from torchtext.vocab import GloVe,FastText,CharNGram\n",
    "import torch.nn as nn\n",
    "import torch.optim as optim\n",
    "import torch.nn.functional as F\n",
    "from torch.autograd import Variable\n",
    "import torch\n",
    "from imdb import IMDB\n",
    "import sys"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "is_cuda = torch.cuda.is_available()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "TEXT = data.Field(lower=True,fix_length=200,batch_first=False)\n",
    "LABEL = data.Field(sequential=False,)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "train, test = IMDB.splits(TEXT, LABEL)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "TEXT.build_vocab(train, vectors=GloVe(name='6B', dim=300),max_size=10000,min_freq=10)\n",
    "LABEL.build_vocab(train,)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "train_iter, test_iter = data.BucketIterator.splits((train, test), batch_size=32, device=-1)\n",
    "train_iter.repeat = False\n",
    "test_iter.repeat = False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "class IMDBRnn(nn.Module):\n",
    "    \n",
    "    def __init__(self,vocab,hidden_size,n_cat,bs=1,nl=2):\n",
    "        super().__init__()\n",
    "        self.hidden_size = hidden_size\n",
    "        self.bs = bs\n",
    "        self.nl = nl\n",
    "        self.e = nn.Embedding(n_vocab,hidden_size)\n",
    "        self.rnn = nn.LSTM(hidden_size,hidden_size,nl)\n",
    "        self.fc2 = nn.Linear(hidden_size,n_cat)\n",
    "        self.softmax = nn.LogSoftmax(dim=-1)\n",
    "        \n",
    "    def forward(self,inp):\n",
    "        bs = inp.size()[1]\n",
    "        if bs != self.bs:\n",
    "            self.bs = bs\n",
    "        e_out = self.e(inp)\n",
    "        h0 = c0 = Variable(e_out.data.new(*(self.nl,self.bs,self.hidden_size)).zero_())\n",
    "        rnn_o,_ = self.rnn(e_out,(h0,c0)) \n",
    "        rnn_o = rnn_o[-1]\n",
    "        fc = F.dropout(self.fc2(rnn_o),p=0.8)\n",
    "        return self.softmax(fc)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "n_vocab = len(TEXT.vocab)\n",
    "n_hidden = 100"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "model = IMDBRnn(n_vocab,n_hidden,3,bs=32)\n",
    "model = model.cuda()\n",
    "\n",
    "optimizer = optim.Adam(model.parameters(),lr=1e-3)\n",
    "\n",
    "def fit(epoch,model,data_loader,phase='training',volatile=False):\n",
    "    if phase == 'training':\n",
    "        model.train()\n",
    "    if phase == 'validation':\n",
    "        model.eval()\n",
    "        volatile=True\n",
    "    running_loss = 0.0\n",
    "    running_correct = 0\n",
    "    for batch_idx , batch in enumerate(data_loader):\n",
    "        text , target = batch.text , batch.label\n",
    "        if is_cuda:\n",
    "            text,target = text.cuda(),target.cuda()\n",
    "        \n",
    "        if phase == 'training':\n",
    "            optimizer.zero_grad()\n",
    "        output = model(text)\n",
    "        loss = F.nll_loss(output,target)\n",
    "        \n",
    "        running_loss += F.nll_loss(output,target,size_average=False).data[0]\n",
    "        preds = output.data.max(dim=1,keepdim=True)[1]\n",
    "        running_correct += preds.eq(target.data.view_as(preds)).cpu().sum()\n",
    "        if phase == 'training':\n",
    "            loss.backward()\n",
    "            optimizer.step()\n",
    "    \n",
    "    loss = running_loss/len(data_loader.dataset)\n",
    "    accuracy = 100. * running_correct/len(data_loader.dataset)\n",
    "    \n",
    "    print(f'{phase} loss is {loss:{5}.{2}} and {phase} accuracy is {running_correct}/{len(data_loader.dataset)}{accuracy:{10}.{4}}')\n",
    "    return loss,accuracy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/vishnu/anaconda3/lib/python3.6/site-packages/ipykernel_launcher.py:14: DeprecationWarning: generator 'Iterator.__iter__' raised StopIteration\n",
      "  \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "training loss is   0.7 and training accuracy is 12645/25000     50.58\n",
      "validation loss is  0.69 and validation accuracy is 13300/25000      53.2\n",
      "training loss is  0.68 and training accuracy is 13573/25000     54.29\n",
      "validation loss is  0.67 and validation accuracy is 14305/25000     57.22\n",
      "training loss is  0.55 and training accuracy is 18060/25000     72.24\n",
      "validation loss is  0.46 and validation accuracy is 19808/25000     79.23\n",
      "training loss is  0.37 and training accuracy is 21128/25000     84.51\n",
      "validation loss is  0.38 and validation accuracy is 20839/25000     83.36\n"
     ]
    }
   ],
   "source": [
    "train_losses , train_accuracy = [],[]\n",
    "val_losses , val_accuracy = [],[]\n",
    "\n",
    "for epoch in range(1,5):\n",
    "\n",
    "    epoch_loss, epoch_accuracy = fit(epoch,model,train_iter,phase='training')\n",
    "    val_epoch_loss , val_epoch_accuracy = fit(epoch,model,test_iter,phase='validation')\n",
    "    train_losses.append(epoch_loss)\n",
    "    train_accuracy.append(epoch_accuracy)\n",
    "    val_losses.append(val_epoch_loss)\n",
    "    val_accuracy.append(val_epoch_accuracy)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/vishnu/anaconda3/lib/python3.6/site-packages/ipykernel_launcher.py:14: DeprecationWarning: generator 'Iterator.__iter__' raised StopIteration\n",
      "  \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "training loss is  0.27 and training accuracy is 22338/25000     89.35\n",
      "validation loss is  0.42 and validation accuracy is 20779/25000     83.12\n",
      "training loss is   0.2 and training accuracy is 23158/25000     92.63\n",
      "validation loss is  0.38 and validation accuracy is 21204/25000     84.82\n",
      "training loss is  0.14 and training accuracy is 23886/25000     95.54\n",
      "validation loss is  0.45 and validation accuracy is 21053/25000     84.21\n",
      "training loss is 0.088 and training accuracy is 24368/25000     97.47\n",
      "validation loss is  0.52 and validation accuracy is 21038/25000     84.15\n"
     ]
    }
   ],
   "source": [
    "for epoch in range(1,5):\n",
    "\n",
    "    epoch_loss, epoch_accuracy = fit(epoch,model,train_iter,phase='training')\n",
    "    val_epoch_loss , val_epoch_accuracy = fit(epoch,model,test_iter,phase='validation')\n",
    "    train_losses.append(epoch_loss)\n",
    "    train_accuracy.append(epoch_accuracy)\n",
    "    val_losses.append(val_epoch_loss)\n",
    "    val_accuracy.append(val_epoch_accuracy)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
